package main

import (
	"fmt"
	consulapi "github.com/hashicorp/consul/api"
	"github.com/hashicorp/consul/api/watch"
	"reflect"
	"sync"
)

// watch包的使用方法为：1）使用watch.Parse(查询参数)生成Plan，2）绑定Plan的handler，3）运行Plan

// 定义watcher
type Watcher struct {
	Wp       *watch.Plan            // 总的Services变化对应的Plan
	watchers map[string]*watch.Plan // 对已经进行监控的service作个记录
	RWMutex  *sync.RWMutex
}

func NewWatcher(watchType string, opts map[string]string, consulAddr string) (*Watcher, error) {
	var options = map[string]interface{}{
		"type":   watchType,
		"prefix": "animal", // 一定要指定key，并且这个key要存在，不然会报错
	}
	// 组装请求参数。(监控类型不同，其请求参数不同)
	for k, v := range opts {
		options[k] = v
	}

	wp, err := watch.Parse(options)
	if err != nil {
		fmt.Println(333)
		return nil, err
	}

	w := &Watcher{
		Wp:       wp,
		watchers: make(map[string]*watch.Plan),
		RWMutex:  new(sync.RWMutex),
	}
	wp.Handler = func(idx uint64, data interface{}) {
		fmt.Println(33333, idx, reflect.TypeOf(data))

		switch d := data.(type) {
		case *consulapi.KVPair:
			fmt.Println(444444, d.Key, string(d.Value))
		case consulapi.KVPairs:
			fmt.Println(55555, d)
		default:
			fmt.Printf("不能判断监控的数据类型: %v", &d)
		}
	}

	return w, nil
}

func RegisterWatcher(watchType string, opts map[string]string, consulAddr string) error {
	w, err := NewWatcher(watchType, opts, consulAddr)
	if err != nil {
		fmt.Println(111111, err)
		return err
	}
	defer w.Wp.Stop()
	if err = w.Wp.Run(consulAddr); err != nil {
		fmt.Println("err: ", err)
		return err
	}

	return nil
}

func main() {
	address := "127.0.0.1:8500"
	if err := RegisterWatcher("keyprefix", nil, address); err != nil {
		fmt.Println("启动 consul 的watch监控失败")
	}
}
